/*****************************************************************************
 * args.c: Arguments parsing functions
 *****************************************************************************
 * Copyright (C) 2010 Sam Grandjean
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>

#include "args.h"
#include "util.h"

int parseArgs(const int argc, char **argv, struct Config *config, char *inputfile, const int inputbuffer)
{
	struct option long_options[] = {
		{"format", required_argument, NULL, 'f'},
		{"color", required_argument, NULL, 'c'},
		{"interlaced", no_argument, NULL, 'i'},
		{"background", required_argument, NULL, 'b'},
		{"magnification", required_argument, NULL, 'm'},
		{"tilesize", required_argument, NULL, 't'},
		{"quiet", no_argument, NULL, 'q'},
		{"help", no_argument, NULL, 'h'},
		{"version", no_argument, NULL, 0},
		{0, 0, NULL, 0}
	};
	int option_index = 0;
	int option;
	while ((option = getopt_long(argc, argv, "f:c:ib:m:t:qh?", long_options, &option_index)) != -1) {
		switch (option) {
			case 0:
				if (strcmp(long_options[option_index].name, "version") == 0) {
					return -2;
				}
				break;
			case 'f':
				if (strcmp(str_tolower(optarg), "p") == 0 || strcmp(str_tolower(optarg), "png") == 0) {
					(*config).format = 'p';
				} else if (strcmp(str_tolower(optarg), "j") == 0 || strcmp(str_tolower(optarg), "jpg") == 0 || strcmp(str_tolower(optarg), "jpeg") == 0) {
					(*config).format = 'j';
				} else if (strcmp(str_tolower(optarg), "g") == 0 || strcmp(str_tolower(optarg), "gif") == 0) {
					(*config).format = 'g';
				} else {
					fprintf(stderr, "%s: invalid format\n", argv[0]);
					return -3;
				}
				break;
			case 'c':
				if (strcmp(str_tolower(optarg), "p") == 0 || strcmp(str_tolower(optarg), "palette") == 0) {
					(*config).truecolor = 0;
				} else if (strcmp(str_tolower(optarg), "t") == 0 || strcmp(str_tolower(optarg), "truecolor") == 0) {
					(*config).truecolor = 1;
				} else {
					fprintf(stderr, "%s: invalid color depth\n", argv[0]);
					return -3;
				}
				break;
			case 'i':
				(*config).interlace = 1;
				break;
			case 'b':
				// Prevent ",r,g,b" and "r,g,b," due to strtok
				if (str_count(optarg, ',') != 2) {
					fprintf(stderr, "%s: invalid background color\n", argv[0]);
					return -3;
				}
				int c = 0;
				char *p;
				p = strtok(optarg, ",");
				while (p != NULL) {
					switch (c) {
						case 0:
							(*config).bgcolor.r = atoi(p);
							if (((*config).bgcolor.r == 0 && strcmp(p, "0") != 0) || (*config).bgcolor.r > 255) {
								fprintf(stderr, "%s: invalid background color\n", argv[0]);
								return -3;
							}
							break;
						case 1:
							(*config).bgcolor.g = atoi(p);
							if (((*config).bgcolor.g == 0 && strcmp(p, "0") != 0) || (*config).bgcolor.g > 255) {
								fprintf(stderr, "%s: invalid background color\n", argv[0]);
								return -3;
							}
							break;
						case 2:
							(*config).bgcolor.b = atoi(p);
							if (((*config).bgcolor.b == 0 && strcmp(p, "0") != 0) || (*config).bgcolor.b > 255) {
								fprintf(stderr, "%s: invalid background color\n", argv[0]);
								return -3;
							}
							break;
					}
					p = strtok(NULL, ",");
					c++;
				}
				if (c != 3) {
					fprintf(stderr, "%s: invalid background color\n", argv[0]);
					return -3;
				}
				break;
			case 'm':
				(*config).magnification = atoi(optarg);
				//TODO: Check if multiple of 2 and > 1
				if ((*config).magnification == 0) {
					fprintf(stderr, "%s: invalid magnification\n", argv[0]);
					return -3;
				}
				break;
			case 't':
				(*config).tilesize = atoi(optarg);
				if ((*config).tilesize == 0) {
					fprintf(stderr, "%s: invalid tile size\n", argv[0]);
					return -3;
				}
				break;
			case 'q':
				(*config).quiet = 1;
				break;
			case '?':
				fprintf(stderr, "\n");
			case 'h':
				return -1;
			default:
				abort();
		}
	}

	switch (argc - optind) {
		case 1:
			strncpy(inputfile, argv[optind], inputbuffer);
			break;
		case 0:
			fprintf(stderr, "%s: missing file\n\n", argv[0]);
			return -1;
		default:
			fprintf(stderr, "%s: too many arguments\n\n", argv[0]);
			return -1;
	}

	return 0;
}

